package com.zc.im;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.zc.im.netty.start.ChatServer;
import com.zc.im.util.ImGolbalTypeContext;
import com.zc.im.util.properties.RabbitmqProperties;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.io.InputStream;
import java.util.Properties;

/**
 * Hello world!
 *  @Configuration标志着这个类作为资源被这个应用程序而定义的一个bean
    @EnableAutoConfiguration告诉Spring Boot启动自动添加bean是基于类路径配置，其他Beans以及各种属性的设置
    通常你会为Spring MVC的应用程序添加@EnableWebMvc注解，但是当Spring Boot看见Spring-webmvc在它的类路径下时它会自动添加，
    这个标志着这个应用程序是一个web应用程序，并且自动激活并配置例如DispatcherServlet的配置
    @ComponentScan告诉Spring去寻找其他的组件，配置以及在hello包中的其他services，并且允许它使用controllers组件
 */
@EnableRedisHttpSession
@EnableAutoConfiguration
@SpringBootApplication
@ComponentScan
@EnableConfigurationProperties({RabbitmqProperties.class})
@MapperScan("com.zc.im.mapper")
public class App implements RabbitListenerConfigurer
{
    private static Logger logger = Logger.getLogger(App.class);
    @Autowired
    private static ChatServer chatServer;

    @Autowired
    private static RedisTemplate redisTemplate;
    @Autowired
    private static StringRedisTemplate stringRedisTemplate;

    @ConfigurationProperties("spring.datasource.druid")
    @Bean
    public DataSource dataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryBean() throws Exception {

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/mybatis/*/*.xml"));

        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    public static void main( String[] args ){
        try {
            getStartProperties();
            //api程序
            SpringApplication.run(App.class, args);
            logger.error("SpringBoot Start Success");
            //netty程序
            chatServer.startNettyServer();
            logger.error("Netty Start Success");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void getStartProperties(){
        try{
            //读取配置文件
            Properties properties = new Properties();
            InputStream inputStream = App.class.getClassLoader().getResourceAsStream("config/netty.properties");
            properties.load(inputStream);
            String nettyHostName = properties.getProperty("netty.hostName");
            String nettyPort = properties.getProperty("netty.port");
            String nettyMaxContentLength = properties.getProperty("netty.maxContentLength");
            String nettyCloseOnExpectationFailed = properties.getProperty("netty.closeOnExpectationFailed");
            String nettyWsUri = properties.getProperty("netty.wsUri");
            String nettyWebsocketPath = properties.getProperty("netty.websocketPath");

            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_HOST_NAME, nettyHostName);
            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_PORT, nettyPort);
            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_MAXCONTENT_LENGTH, nettyMaxContentLength);
            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_CLOSE_ON_EXPECTATION_FAILED, nettyCloseOnExpectationFailed);
            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_WS_URI, nettyWsUri);
            ImGolbalTypeContext.propertiesMap.put(ImGolbalTypeContext.NETTY_WEB_SOCKET_PATH, nettyWebsocketPath);
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }

    }


    @Bean
    public MappingJackson2MessageConverter jackson2Converter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        return converter;
    }

    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(jackson2Converter());
        return factory;
    }


    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }



}
